/*
    作者：zx
    时间：2023.1.13
    描述：应用程序通过此文件函数调用 调用门 
*/

#ifndef LIB_SYSCALL_H
#define LIB_SYSCALL_H

#include "os_cfg.h"
#include "core/syscall.h"
#include <sys/stat.h> 

// 当应用程序调用调用门时，需要切换栈，
// 首先把参数压入正常栈，然后切换到内核栈，复制正常栈参数进内核栈
// 此结构体包含需要复制的参数
// 参数个数参考 cpu.c中 init_gdt中的SYSCALL_PARAM_COUNT
typedef struct _syscall_args_t
{
    int id;         // 系统调用的ID
    int arg0, arg1, arg2, arg3;
}syscall_args_t;

static inline int sys_call(syscall_args_t * args)
{
    //                offset,            selector | RPL
    const unsigned long addr[] = {0, SYSTEM_SELECTOR_SYSCALL | 0};
    int ret;
    __asm__ __volatile__(
        "push %[arg3]\n\t"
        "push %[arg2]\n\t"
        "push %[arg1]\n\t"
        "push %[arg0]\n\t"
        "push %[id]\n\t"
        "lcalll *(%[v])\n\t":"=a"(ret)
                            :[arg3]"r"(args->arg3),
                            [arg2]"r"(args->arg2),
                            [arg1]"r"(args->arg1),
                            [arg0]"r"(args->arg0),
                            [id]"r"(args->id),
                            [v]"r"(addr)
    );
    return ret;
}

void msleep(int ms);
int get_present_id(void);
void print_msg(char * fmt, int arg);
int fork(void);
int execve(const char * name, char * const * argv, char * const *  env);
int yield(void);

// 文件系统接口
int open(const char * name, int flag, ...);
int read(int file, char * ptr, int len);
int write(int file, char * ptr, int len);
int close(int file);
int lseek(int file, int ptr, int dir); 
int ioctl(int file, int cmd, int arg0, int arg1);            // 回显控制
int unlink(const char * name);


// newlib库所需的系统调用
int isatty(int file);
int fstat(int file, struct stat *st);
void * sbrk(ptrdiff_t incr);
// 申请进程文件打开表中空闲项，连接到已经有的file指向的file_t
int dup(int file);

// 进程退出
void _exit(int status);
// 进程资源回收
int wait(int * status);


// 文件系统展示相关
struct dirent       // FAT16 根目录区中表项的信息
{
    int index; 
    int type;
    char name[255];
    int size;
};

typedef struct _DIR // 一个表项结构
{
    int index;              // 当前扫描的位置
    struct dirent dirent;   //
}DIR;

DIR * opendir(const char * path);
struct dirent * readdir(DIR * dir);
int closedir(DIR * dir);


#endif // !LIB_SYSCALL_H